import os
import re
import sys
import json
import subprocess
import importlib.util
import xml.etree.ElementTree as ET
from tqdm import tqdm
import requests

# 依赖检查与安装
def install_package(package):
    try:
        subprocess.check_call([sys.executable, "-m", "pip", "install", package])
        return True
    except Exception as e:
        print(f"❌ 安装{package}失败: {str(e)}")
        return False

def check_and_install_dependencies():
    required_packages = ['requests', 'tqdm']
    for package in required_packages:
        if importlib.util.find_spec(package) is None:
            print(f"⚠️ 未检测到{package}，正在安装...")
            if not install_package(package):
                print(f"❌ 缺少必要依赖{package}，程序无法运行")
                sys.exit(1)
    print("✅ 所有必要依赖已就绪")

# 文件名清理
def clean_filename(name):
    invalid_chars = r'[\/:*?"<>|]'
    cleaned = re.sub(invalid_chars, '_', name)
    return cleaned.encode('utf-8', errors='replace').decode('utf-8')

# 文件下载
def download_single_file(url, save_path, desc):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Referer": "https://www.bilibili.com/",
        "Range": "bytes=0-"
    }
    
    try:
        response = requests.get(url, headers=headers, stream=True)
        response.raise_for_status()
        file_size = int(response.headers.get('content-length', 0))
        
        with open(save_path, 'wb') as f, tqdm(
            total=file_size,
            unit='B',
            unit_scale=True,
            unit_divisor=1024,
            desc=desc
        ) as pbar:
            for chunk in response.iter_content(chunk_size=1024*1024):
                if chunk:
                    f.write(chunk)
                    pbar.update(len(chunk))
        print(f"✅ 已保存至: {save_path}")
        return True
    except Exception as e:
        print(f"❌ 下载失败: {str(e)}")
        return False

# 弹幕处理
def download_danmu(bv_id, cid, save_path):
    danmu_url = f"https://api.bilibili.com/x/v1/dm/list.so?oid={cid}"
    return download_single_file(danmu_url, save_path, "下载弹幕")

def parse_danmu_xml(xml_file):
    try:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        danmus = []
        
        for d in root.findall('d'):
            attrs = d.get('p').split(',')
            timestamp = float(attrs[0])
            minutes = int(timestamp // 60)
            seconds = timestamp % 60
            time_str = f"{minutes:02d}:{seconds:06.3f}"
            content = d.text
            danmus.append((time_str, content))
        
        return danmus
    except Exception as e:
        print(f"解析弹幕失败: {e}")
        return []

def process_danmu(xml_path, txt_path):
    danmus = parse_danmu_xml(xml_path)
    if not danmus:
        return False
        
    with open(txt_path, 'w', encoding='utf-8') as f:
        for time_str, content in danmus:
            f.write(f"[{time_str}] {content}\n")
    
    print(f"✅ 弹幕处理完成: {os.path.basename(txt_path)}")
    # 修复此处的语法错误：完整判断并删除临时文件
    if os.path.exists(xml_path):
        os.remove(xml_path)
    return True

# FFmpeg相关
def check_ffmpeg():
    try:
        subprocess.run(["ffmpeg", "-version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        return True
    except (FileNotFoundError, subprocess.CalledProcessError):
        return False

def convert_media(input_path, output_path, media_type):
    try:
        if media_type == 'video':
            cmd = [
                "ffmpeg", "-y",
                "-i", input_path,
                "-c:v", "copy",
                "-f", "mp4",
                output_path
            ]
        elif media_type == 'audio':
            cmd = [
                "ffmpeg", "-y",
                "-i", input_path,
                "-c:a", "libmp3lame",
                "-q:a", "2",
                output_path
            ]
        
        subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(f"✅ 格式转换完成，已保存至: {output_path}")
        return True
    except Exception as e:
        print(f"❌ 格式转换失败: {str(e)}")
        return False

def merge_media(video_path, audio_path, output_path):
    try:
        cmd = [
            "ffmpeg", "-y",
            "-i", video_path,
            "-i", audio_path,
            "-c:v", "copy",
            "-c:a", "copy",
            output_path
        ]
        subprocess.run(cmd, check=True)
        print(f"✅ 音视频合并完成，已保存至: {output_path}")
        return True
    except Exception as e:
        print(f"❌ 合并失败: {str(e)}")
        return False

# 视频信息与评论
def save_video_info(info, save_path):
    try:
        with open(save_path, 'w', encoding='utf-8') as f:
            json.dump(info, f, ensure_ascii=False, indent=2)
        print(f"✅ 视频信息已保存至: {save_path}")
    except Exception as e:
        print(f"❌ 保存视频信息失败: {str(e)}")

def get_cid_from_bv(bv_id):
    from api import get_bilibili_video_info
    info = get_bilibili_video_info(bv_id)
    return info.get('cid') if info else None

def get_video_comments(bv_id, page=3):
    comments = []
    try:
        cid = get_cid_from_bv(bv_id)
        if not cid:
            print("❌ 无法获取CID，无法获取评论")
            return []
            
        for p in range(1, page+1):
            url = f"https://api.bilibili.com/x/v2/reply?type=1&oid={cid}&pn={p}&ps=20"
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
                "Referer": f"https://www.bilibili.com/video/{bv_id}"
            }
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            data = response.json()
            
            if data.get("code") != 0:
                break
            replies = data.get("data", {}).get("replies", [])
            for reply in replies:
                comments.append({
                    "用户": reply.get('member', {}).get('uname'),
                    "评论内容": reply.get('content', {}).get('message'),
                    "点赞数": reply.get('like')
                })
        return comments
    except Exception as e:
        print(f"❌ 获取评论失败: {str(e)}")
        return []

def save_comments(comments, save_path):
    try:
        with open(save_path, 'w', encoding='utf-8') as f:
            for i, cmt in enumerate(comments, 1):
                f.write(f"评论{i}：{cmt['用户']}（点赞：{cmt['点赞数']}）\n")
                f.write(f"内容：{cmt['评论内容']}\n\n")
        print(f"✅ 评论已保存至: {save_path}")
    except Exception as e:
        print(f"❌ 保存评论失败: {str(e)}")
